package com.iplant.pdm.serviceImpl.dao.fpc;

import com.alibaba.fastjson.JSON;
import com.iplant.base.po.enums.DBSchemas;
import com.iplant.base.utils.annotation.dao.DBBaseDAO;
import com.iplant.pdm.service.po.bop.FPCRoute;
import com.iplant.pdm.service.po.bop.FPCRoutePart;
import com.iplant.pdm.service.po.bop.FPCRoutePartPoint;
import com.iplant.base.po.OutResult;
import com.iplant.base.po.Pagination;
import com.iplant.base.po.enums.ExceptionTypes;
import com.iplant.base.utils.general.StringUtils;
import com.iplant.base.utils.sql.BaseDAO;
import com.iplant.basic.service.po.bms.BMSEmployee;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

@DBBaseDAO(FPCRoutePart.class)
public class FPCRoutePartDAO extends BaseDAO {
    private static FPCRoutePartDAO Instance = null;

    private static Logger logger = LoggerFactory.getLogger(FPCRoutePartDAO.class);

    private FPCRoutePartDAO() {
        super("");
        this.Init();
    }

    public static FPCRoutePartDAO getInstance() {
        if (Instance == null)
            Instance = new FPCRoutePartDAO();
        return Instance;
    }

    /**
     * 自身除开的最大版本号
     *
     * @param wLoginUser
     * @param wName
     * @param wErrorCode
     * @return
     */
    private int FPC_GetMaxVersion(BMSEmployee wLoginUser, String wName, OutResult<Integer> wErrorCode) {

        int wMaxVersion = 0;
        wErrorCode.set(0);

        try {

            String wSQLText = StringUtils.Format(
                    "select Max(SUBSTRING_INDEX(t.Code,CONCAT(t.Name,''.V_''),-1)+0 ) as ItemCount ,t.Name"
                            + "  from  {0}.fpc_routepart t where locate(t.Name,t.Code)=1 and t.Name=:Name group by " +
                            "Name ;",
                    super.getDBName());

            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("Name", wName);

            List<Map<String, Object>> wQueryResultList = super.queryForList(wSQLText, wParams);

            for (Map<String, Object> wSqlDataReader : wQueryResultList) {
                wMaxVersion = StringUtils.parseInt(wSqlDataReader.get("ItemCount"));
            }

        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());

            logger.error("FPC_UpdateRoute", ex);
        }
        return wMaxVersion;
    }


    public void FPC_UpdateRoutePart(BMSEmployee wLoginUser, FPCRoutePart wRoutePart, OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);

        try {
            if (wRoutePart == null || StringUtils.isEmpty(wRoutePart.Name)) {
                wErrorCode.set(ExceptionTypes.Parameter.getValue());
                return;
            }
            FPCRoutePart wRoutePartO = this.FPC_CheckRoutePart(wLoginUser, wRoutePart, wErrorCode);
            if (wRoutePartO.ID > 0) {
                wErrorCode.set(ExceptionTypes.Duplication.getValue());
            }
            if (wErrorCode.Result != 0)
                return;


            if (wRoutePart.ID <= 0 || !wRoutePart.Code.startsWith(wRoutePart.Name)) {

                int wVersion = this.FPC_GetMaxVersion(wLoginUser, wRoutePart.Name, wErrorCode);

                wRoutePart.Code = StringUtils.Format("{0}.V_{1}", wRoutePart.Name, String.format("%04d", wVersion + 1));
            }


            Map<String, Object> wParams = new HashMap<String, Object>();

            wParams.put("RouteID", wRoutePart.RouteID);
            wParams.put("Version", wRoutePart.Version);

            wParams.put("PartCode", wRoutePart.PartCode);
            wParams.put("PartType", wRoutePart.PartType);
            wParams.put("FQTY", wRoutePart.FQTY);
            wParams.put("Period", wRoutePart.Period);
            wParams.put("OrderID", wRoutePart.OrderID);
            wParams.put("PrevPartID", wRoutePart.PrevPartID);
            wParams.put("ChangeControl", wRoutePart.ChangeControl);
            wParams.put("ControlPartID", StringUtils.Join(",", wRoutePart.ControlPartID));
            wParams.put("PartFile", wRoutePart.PartFile);

            wParams.put("NextPartIDMap", JSON.toJSONString(wRoutePart.NextPartIDMap));
            wParams.put("NextPartID", StringUtils.Join(",", wRoutePart.NextPartID));

            wParams.put("Name", wRoutePart.Name);
            wParams.put("Code", wRoutePart.Code);
            wParams.put("Description", wRoutePart.Description);

            wParams.put("EditorID", wLoginUser.getID());
            wParams.put("EditTime", Calendar.getInstance());
            wParams.put("Active", wRoutePart.Active);

            if (wRoutePart.ID > 0) {
                wParams.put("ID", wRoutePart.ID);
                super.Update(super.getTableName("fpc_routepart"), "ID", wParams);
            } else {
                wParams.put("CreatorID", wLoginUser.getID());
                wParams.put("CreateTime", Calendar.getInstance());
                wRoutePart.ID = super.Insert(super.getTableName("fpc_routepart"), wParams);
            }

        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error("FPC_UpdateRoutePart", ex);
        }
    }

    public void FPC_DeleteRoutePart(BMSEmployee wLoginUser, int wID, OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);

        try {
            if (wID <= 0) {
                wErrorCode.set(ExceptionTypes.Parameter.getValue());
                return;
            }

            Map<String, Object> wParams = new HashMap<String, Object>();

            wParams.put("ID", wID);

            int wRow = super.Delete(super.getTableName("fpc_routepart"), wParams, " AND ID>0 AND Active=0");
            if (wRow > 0) {
                String wSQLText = StringUtils.Format(
                        "Delete from {0}.fpc_routepartpoint  Where ID>0 AND RoutePartID=:ID ;",
                        super.getDBName());
                super.update(wSQLText, wParams);

            }
        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error("FPC_DeleteRoutePart", ex);
        }
    }

    public void FPC_ActiveRoutePart(BMSEmployee wLoginUser, FPCRoutePart wRoutePart, int wActive,
                                    OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);
        // 判断客户信息是否存在(中国：统一社会信用代码，国外:提醒是否有重复）

        try {
            if (wRoutePart == null || wRoutePart.ID <= 0) {
                wErrorCode.set(ExceptionTypes.Parameter.getValue());
                return;
            }

            Map<String, Object> wParams = new HashMap<String, Object>();

            wParams.put("ID", wRoutePart.ID);
            wParams.put("EditorID", wLoginUser.getID());
            wParams.put("EditTime", Calendar.getInstance());
            wParams.put("Active", wActive);
            super.Update(super.getTableName("fpc_routepart"), "ID", wParams);

        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());

            logger.error("FPC_ActiveRoutePart", ex);
        }
    }

    public List<FPCRoutePart> FPC_QueryRoutePartList(BMSEmployee wLoginUser, List<Integer> wRouteID, String wName,
                                                     String wPartCode, String wNameLike, int wActive, int wHasItem,
                                                     Pagination wPagination,
                                                     OutResult<Integer> wErrorCode) {
        return this.FPC_QueryRoutePartList(wLoginUser, -1, "", wRouteID, wName, wPartCode, wNameLike, wActive, wHasItem,
                wPagination, wErrorCode);
    }

    public List<FPCRoutePart> FPC_QueryRoutePartList(BMSEmployee wLoginUser, Integer wRouteID, int wActive,
                                                     int wHasItem, Pagination wPagination,
                                                     OutResult<Integer> wErrorCode) {
        return this.FPC_QueryRoutePartList(wLoginUser, -1, "", StringUtils.parseListArgs(wRouteID), "", "", "", wActive,
                wHasItem, wPagination, wErrorCode);
    }

    @SuppressWarnings("unchecked")
    private List<FPCRoutePart> FPC_QueryRoutePartList(BMSEmployee wLoginUser, int wID, String wCode,
                                                      List<Integer> wRouteID, String wName, String wPartCode,
                                                      String wNameLike, int wActive, int wHasItem,
                                                      Pagination wPagination, OutResult<Integer> wErrorCode) {
        List<FPCRoutePart> wRoutePartList = new ArrayList<FPCRoutePart>();
        wErrorCode.set(0);

        try {
            if (wRouteID == null)
                wRouteID = new ArrayList<Integer>();

            wRouteID.removeIf(p -> p <= 0);

            // Step02:查询
            Map<String, Object> wParams = new HashMap<String, Object>();
            String wSQLText = "";
            wSQLText = StringUtils.Format(
                    "Select t.*,t2.Name as RouteName,t2.Code as RouteCode,t2.Version as RouteVersion,"
                            + " t3.Name as CreatorName ,t4.Name as EditorName, t5.Name as PrevRoutePartName,"
                            + " group_concat(distinct t6.Name) as NextPartName ,group_concat(distinct t7.Name) as " +
                            "ControlPartName,"
                            + " count(t8.ID) as ItemCount,sum(t8.StandardPeriod) as StandardPeriod,"
                            + " sum(t8.ActualPeriod) as ActualPeriod   from {0}.fpc_routepart t  "
                            + " left join {0}.fpc_route t2 on t.RouteID=t2.ID "
                            + " left join {0}.mbs_user t3 on t.CreatorID=t3.ID "
                            + " left join {0}.mbs_user t4 on t.EditorID=t4.ID "
                            + " left join {0}.fpc_routepart t5 on t.PrevPartID=t5.ID "
                            + " left join {0}.fpc_routepart t6 on find_in_set(t6.ID,t.NextPartID) "
                            + " left join {0}.fpc_routepart t7 on find_in_set(t7.ID,t.ControlPartID) "
                            + " left join {0}.fpc_routepartpoint t8 on t.ID=t8.RoutePartID"
                            + " where (:ID<=0 or  t.ID=:ID) and (:Code =''''  or  t.Code=:Code)"
                            + " and (:Name =''''  or  t.Name=:Name)  and (:PartCode =''''  or  t.PartCode=:PartCode) "
                            + " AND (:Active<0 or  t.Active=:Active) AND (:NameLike = '''' or  t.Name like :NameLike)  "
                            + " AND (:RouteID = '''' or  t.RouteID IN ({1}) ) group by t.ID ",
                    super.getDBName(), wRouteID.size() > 0 ? StringUtils.Join(",", wRouteID) : "0");

            wSQLText = this.DMLChange(wSQLText);

            wParams.put("ID", wID);
            wParams.put("Code", wCode);
            wParams.put("Name", wName);
            wParams.put("PartCode", wPartCode);
            wParams.put("Active", wActive);
            wParams.put("NameLike", StringUtils.isEmpty(wNameLike) ? "" : ("%" + wNameLike + "%"));
            wParams.put("RouteID", StringUtils.Join(",", wRouteID));

            List<Map<String, Object>> wQueryResultList = super.queryForList(wSQLText, wParams, wPagination);

            FPCRoutePart wRoutePart = null;
            List<Integer> wRoutePartID = new ArrayList<Integer>();
            for (Map<String, Object> wSqlDataReader : wQueryResultList) {
                wRoutePart = new FPCRoutePart();
                wRoutePart.ID = StringUtils.parseInt(wSqlDataReader.get("ID"));
                wRoutePart.Code = StringUtils.parseString(wSqlDataReader.get("Code"));
                wRoutePart.Name = StringUtils.parseString(wSqlDataReader.get("Name"));
                wRoutePart.Version = StringUtils.parseString(wSqlDataReader.get("Version"));
                wRoutePart.RouteID = StringUtils.parseInt(wSqlDataReader.get("RouteID"));
                wRoutePart.RouteCode = StringUtils.parseString(wSqlDataReader.get("RouteCode"));
                wRoutePart.RouteName = StringUtils.parseString(wSqlDataReader.get("RouteName"));
                wRoutePart.RouteVersion = StringUtils.parseString(wSqlDataReader.get("RouteVersion"));
                wRoutePart.PartCode = StringUtils.parseString(wSqlDataReader.get("PartCode"));
                wRoutePart.PartType = StringUtils.parseInt(wSqlDataReader.get("PartType"));
                wRoutePart.FQTY = StringUtils.parseFloat(wSqlDataReader.get("FQTY"));
                wRoutePart.Period = StringUtils.parseInt(wSqlDataReader.get("Period"));
                wRoutePart.OrderID = StringUtils.parseInt(wSqlDataReader.get("OrderID"));
                wRoutePart.PrevPartID = StringUtils.parseInt(wSqlDataReader.get("PrevPartID"));
                wRoutePart.PrevPartName = StringUtils.parseString(wSqlDataReader.get("PrevPartName"));
                wRoutePart.ChangeControl = StringUtils.parseInt(wSqlDataReader.get("ChangeControl"));
                wRoutePart.ControlPartID = StringUtils.parseIntList(wSqlDataReader.get("ControlPartID"), ",");
                wRoutePart.ControlPartName = StringUtils.parseString(wSqlDataReader.get("ControlPartName"));
                wRoutePart.StandardPeriod = StringUtils.parseDouble(wSqlDataReader.get("StandardPeriod"));
                wRoutePart.ActualPeriod = StringUtils.parseDouble(wSqlDataReader.get("ActualPeriod"));
                wRoutePart.ItemCount = StringUtils.parseInt(wSqlDataReader.get("ItemCount"));
                wRoutePart.PartFile = StringUtils.parseString(wSqlDataReader.get("PartFile"));

                wRoutePart.NextPartID = StringUtils.parseIntList(wSqlDataReader.get("NextPartID"), ",");
                wRoutePart.NextPartName = StringUtils.parseString(wSqlDataReader.get("NextPartName"));

                wRoutePart.NextPartIDMap = JSON
                        .parseObject(StringUtils.parseString(wSqlDataReader.get("NextPartIDMap")), Map.class);

                wRoutePart.Active = StringUtils.parseInt(wSqlDataReader.get("Active"));
                wRoutePart.CreatorID = StringUtils.parseInt(wSqlDataReader.get("CreatorID"));
                wRoutePart.EditorID = StringUtils.parseInt(wSqlDataReader.get("EditorID"));
                wRoutePart.CreatorName = StringUtils.parseString(wSqlDataReader.get("CreatorName"));
                wRoutePart.EditorName = StringUtils.parseString(wSqlDataReader.get("EditorName"));
                wRoutePart.CreateTime = StringUtils.parseCalendar(wSqlDataReader.get("CreateTime"));
                wRoutePart.EditTime = StringUtils.parseCalendar(wSqlDataReader.get("EditTime"));
                wRoutePart.Description = StringUtils.parseString(wSqlDataReader.get("Description"));

                wRoutePartList.add(wRoutePart);

                if (!wRoutePartID.contains(wRoutePart.ID))
                    wRoutePartID.add(wRoutePart.ID);
            }
            if (wHasItem == 1) {

                List<FPCRoutePartPoint> wRoutePartPointList = FPCRoutePartPointDAO.getInstance()
                        .FPC_QueryRoutePartPointList(wLoginUser, -1, wRoutePartID, "", "", "", "", "", -1, wHasItem,
                                Pagination.getMaxSize(), wErrorCode);
                if (wRoutePartPointList == null || wRoutePartPointList.size() == 0)
                    return wRoutePartList;

                Map<Integer, List<FPCRoutePartPoint>> wRoutePartPointDic = wRoutePartPointList.stream()
                        .collect(Collectors.groupingBy(p -> p.RoutePartID));

                for (FPCRoutePart fpcRoutePart : wRoutePartList) {
                    if (fpcRoutePart == null || fpcRoutePart.ID <= 0
                            || !wRoutePartPointDic.containsKey(fpcRoutePart.ID))
                        continue;

                    fpcRoutePart.PartPointList = wRoutePartPointDic.get(fpcRoutePart.ID);
                }

            }

            // Step03:配置系统
        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error("FPC_QueryRoutePartList", ex);
        }
        return wRoutePartList;
    }

    public FPCRoutePart FPC_QueryRoutePart(BMSEmployee wLoginUser, int wID, String wCode,
                                           OutResult<Integer> wErrorCode) {
        FPCRoutePart wResult = new FPCRoutePart();
        wErrorCode.set(0);

        try {
            List<FPCRoutePart> wList = null;
            if (wID > 0) {
                wList = this.FPC_QueryRoutePartList(wLoginUser, wID, "", null, "", "", "", -1, 1,
                        Pagination.getDefault(), wErrorCode);

            } else if (StringUtils.isNotEmpty(wCode)) {
                wList = this.FPC_QueryRoutePartList(wLoginUser, -1, wCode, null, "", "", "", -1, 1,
                        Pagination.getDefault(), wErrorCode);
            }
            if (wList != null && wList.size() > 0) {
                wResult = wList.get(0);
            }
        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error("FPC_QueryRoutePartByID", ex);
        }
        return wResult;
    }

    public FPCRoutePart FPC_QueryRoutePart(BMSEmployee wLoginUser, int wRouteID, String wPartCode, String wName,
                                           OutResult<Integer> wErrorCode) {
        FPCRoutePart wResult = new FPCRoutePart();
        wErrorCode.set(0);

        try {
            if (wRouteID <= 0)
                return wResult;
            List<FPCRoutePart> wList = null;
            if (StringUtils.isNotEmpty(wName)) {
                wList = this.FPC_QueryRoutePartList(wLoginUser, -1, "", StringUtils.parseListArgs(wRouteID), wName, "",
                        "", -1, 1, Pagination.getDefault(), wErrorCode);

            } else if (StringUtils.isNotEmpty(wPartCode)) {
                wList = this.FPC_QueryRoutePartList(wLoginUser, -1, "", StringUtils.parseListArgs(wRouteID), "",
                        wPartCode, "", -1, 1, Pagination.getDefault(), wErrorCode);
            }
            if (wList != null && wList.size() > 0) {
                wResult = wList.get(0);
            }
        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error("FPC_QueryRoutePartByID", ex);
        }
        return wResult;
    }

    public FPCRoutePart FPC_CheckRoutePart(BMSEmployee wLoginUser, FPCRoutePart wFPCRoutePart,
                                           OutResult<Integer> wErrorCode) {
        FPCRoutePart wRoutePart = new FPCRoutePart();
        wErrorCode.set(0);

        try {

            // Step0:查询
            Map<String, Object> wParams = new HashMap<String, Object>();
            String wSQLText = StringUtils.Format("Select * from {0}.fpc_routepart "
                    + " where ID!=:ID and ( Code=:Code or" + " (RouteID=:RouteID and " + " ( Name =:Name or "
                    + " (:PartCode !='''' and  PartCode=:PartCode)  ))  ) ", super.getDBName());
            wParams.clear();
            wParams.put("ID", wFPCRoutePart.ID);
            wParams.put("Name", wFPCRoutePart.Name);
            wParams.put("Code", wFPCRoutePart.Code);
            wParams.put("RouteID", wFPCRoutePart.RouteID);
            wParams.put("PartCode", wFPCRoutePart.PartCode);

            wSQLText = this.DMLChange(wSQLText);
            List<Map<String, Object>> wQueryResultList = super.queryForList(wSQLText, wParams);
            for (Map<String, Object> wSqlDataReader : wQueryResultList) {
                wRoutePart.ID = StringUtils.parseInt(wSqlDataReader.get("ID"));
                wRoutePart.Name = StringUtils.parseString(wSqlDataReader.get("Name"));
                wRoutePart.Code = StringUtils.parseString(wSqlDataReader.get("Code"));
                wRoutePart.PartCode = StringUtils.parseString(wSqlDataReader.get("PartCode"));

                wRoutePart.PartType = StringUtils.parseInt(wSqlDataReader.get("PartType"));
                wRoutePart.RouteID = StringUtils.parseInt(wSqlDataReader.get("RouteID"));
                wRoutePart.CreatorID = StringUtils.parseInt(wSqlDataReader.get("CreatorID"));
                wRoutePart.CreateTime = StringUtils.parseCalendar(wSqlDataReader.get("CreateTime"));
                wRoutePart.EditorID = StringUtils.parseInt(wSqlDataReader.get("EditorID"));
                wRoutePart.EditTime = StringUtils.parseCalendar(wSqlDataReader.get("EditTime"));
                wRoutePart.Active = StringUtils.parseInt(wSqlDataReader.get("Active"));

            }

        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error("FPC_CheckRoutePart", ex);
        }
        return wRoutePart;
    }

    public void DeleteList(BMSEmployee wLoginUser, List<FPCRoutePart> wFPCRoutePartDelete, OutResult<Integer> wErrorCode) {
        List<String> wResult = new ArrayList<String>();
        try {
            if (wFPCRoutePartDelete == null || wFPCRoutePartDelete.size() <= 0) {
                return;
            }

            List<Integer> wIDList = wFPCRoutePartDelete.stream().map(p -> p.ID).distinct().collect(Collectors.toList());

            String wSQL = StringUtils.Format("DELETE FROM {0}.`fpc_routepart` WHERE ID IN ({1});",
                    DBSchemas.PDM.getDBName(), StringUtils.Join(",", wIDList));

            Map<String, Object> wParamMap = new HashMap<String, Object>();

            wSQL = this.DMLChange(wSQL);

            this.update(wSQL, wParamMap);
        } catch (Exception ex) {
            logger.error(ex.toString());
        }
    }
}
